#! /usr/bin/env python

# -*- coding: UTF-8 -*-
# ==============================================================================
# Filename : MainUI.py
# Purpose  : 
# Author   : Yohann Li (lyh001686@sina.com)
# Date     : 2020-07-01 17:19
# ==============================================================================
import functools
import os
import sys

from PyQt5.QtCore import QObject
from PyQt5.QtGui import QFont
# from PyQt5.QtCore import pyqtSlot, Qt
from PyQt5.QtWidgets import QMainWindow, QMenu, QApplication, QFileDialog, QPlainTextEdit, QStatusBar, QAction, \
    QFontDialog

from Widgets.AboutReader import AboutReader
from Widgets.HighlightText import TextHighlighter
from Widgets.Highlighter2 import Highlighter
# from Widgets.NotificationBox import NoteBox
from Widgets.ReceiveCMD import ReceiceCMDEdit
from Widgets.ReferNotes import ReferenceNotes
from Widgets.TabWidget import TabWidget, SerialEdit, SerialFrame, ReaderEdit
from Widgets.Preferences import Preferences
from Widgets.CheckUpdate import CheckUpdate
from conf.settings import Setting
from conf.configuration import logger, APPNAME, tool_path


class UI(QMainWindow):

    def __init__(self, *args, **kwargs):
        super(UI, self).__init__(*args, **kwargs)
        self.setObjectName('mainwindow')
        self.tab_widget = TabWidget(self)  # 标签框架
        self.setCentralWidget(self.tab_widget)  # 设置中央控件
        self.setup_file_menu()
        self.setup_edit_menu()
        self.setup_format_menu()
        self.setup_tools_menu()
        self.setup_debug_menu()
        self.setup_help_menu()
        self.set_status_bar()
        # self.check_updates(silent=True)
        # self.show_refer_notes()

    def set_status_bar(self):
        status_bar = QStatusBar()
        status_bar.setObjectName('statusbar')
        self.setStatusBar(status_bar)

    def set_status_bar_msg(self, msg: str = ''):
        self.statusBar().showMessage(msg, 3000)

    @functools.lru_cache()
    def read_file_by_directly(self, path: str):
        """直接使用python读取文件"""
        with open(path, 'rb') as f:
            logger.debug(f'Reading file {path}')
            text = f.read().decode('utf8', errors='ignore')
            logger.debug(f"Finished to read file of size {os.path.getsize(path)}")
            return text

    def setup_file_menu(self):
        file_menu = QMenu("&File", self)
        self.menuBar().addMenu(file_menu)

        file_menu.addAction("&New...", self.new_file, "Ctrl+N")
        file_menu.addAction("&Open...", self.open_file, "Ctrl+O")
        file_menu.addAction("S&erial...", self.open_serial, "Ctrl+e")
        file_menu.addAction("&Save...", self.save_to_file, "Ctrl+s")
        file_menu.addAction("&Save as...", self.save_as_file, "Ctrl+Shift+s")
        file_menu.addAction("E&xit", QApplication.instance().quit, "Ctrl+Q")
        # file_menu.addAction("About &Qt", QApplication.instance().aboutQt)
        file_menu.addAction(f"About {APPNAME}", self.show_about)
        # file_menu.addAction(f"Settings", self.open_preferences, 'Ctrl+,').setMenuRole(QAction.PreferencesRole)

    def setup_edit_menu(self):
        menu = QMenu("&Edit", self)
        self.menuBar().addMenu(menu)

        menu.addAction('Clear', self.tab_widget.clear_edit_content, 'Ctrl+K')

    def setup_format_menu(self):
        menu = QMenu("&Format", self)
        self.menuBar().addMenu(menu)
        menu.addAction('Font', self.set_font)
        menu.addAction('Syntax Highlighter', self.edit_highlighter)

    def setup_tools_menu(self):
        menu = QMenu("&Tools", self)
        menu.setObjectName('toolsmenu')
        menu.addAction('ssh as root', self.ssh_as_root, 'Ctrl+R')
        self.menuBar().addMenu(menu)

        menu.addAction('Browse remote device', self.browse_rmt_dev, 'Ctrl+B')
        menu.addAction('Get sysdiagnose', self._get_sysdiagnose)
        menu.addAction('Get BurnIn Logs', self._get_burninlog)
        menu.addAction(f"Run given cmds", self._run_given_cmds)

    def setup_debug_menu(self):
        menu = QMenu("&Debug", self)
        menu.setObjectName('debugmenu')
        menu.addAction('Inspect children', self.inspect_children)
        self.menuBar().addMenu(menu)

    def setup_help_menu(self):
        menu = QMenu("&Help", self)
        menu.addAction(f"Check for Updates...", self.check_updates)
        # menu.addAction("Instruction", self.open_instruction)
        self.menuBar().addMenu(menu)

    def set_font(self):
        """设置当前eidtor的字体"""
        edit_ = self.tab_widget.currentWidget().t
        font_, ok_ = QFontDialog.getFont(QFont(edit_.font()), self)
        logger.info(f"Modifing font to {font_}")
        edit_.setFont(font_)

    def open_instruction(self):
        fname = 'LogViewer Instruction.pdf'
        f_path = os.path.join(tool_path, fname)
        os.popen(f"open {repr(f_path)}")

    addtional_win = []
    def edit_highlighter(self):
        thl = TextHighlighter()
        thl.re_highlighter.connect(self.re_highlight)
        self.addtional_win.append(thl)
        thl.show()

    def re_highlight(self):
        for edit_ in self.findChildren(QPlainTextEdit):
            edit_.highlighter = Highlighter(edit_.document())
            # edit_.highlighter.reset()

    def _run_given_cmds(self):
        recv_edit = ReceiceCMDEdit()
        self.addtional_win.append(recv_edit)
        cur_widget = self.tab_widget.currentWidget()
        if cur_widget.objectName() == 'serialpage':
            recv_edit.text_signal.connect(cur_widget.run_jayson_cmds)
            recv_edit.show()

    def open_preferences(self):
        _p = Preferences()
        self.addtional_win.append(_p)
        _p.show()

    def browse_rmt_dev(self):
        cur_widget = self.tab_widget.currentWidget()
        if cur_widget.objectName() == 'serialpage':
            cur_widget.open_treeview()

    def ssh_as_root(self):
        cur_widget = self.tab_widget.currentWidget()
        if cur_widget.objectName() == 'serialpage':
            cur_widget.openSSH()

    def _get_sysdiagnose(self):
        cur_widget = self.tab_widget.currentWidget()
        if cur_widget.objectName() == 'serialpage':
            cur_widget.get_sysdiagnose()

    def _get_burninlog(self):
        cur_widget = self.tab_widget.currentWidget()
        if cur_widget.objectName() == 'serialpage':
            cur_widget.get_astro()

    def show_about(self):
        about_win = AboutReader()
        self.addtional_win.append(about_win)
        about_win.show()

    def check_updates(self, silent: bool = False):
        cur_v = QApplication.applicationVersion()
        check_update_window = CheckUpdate(current_v=cur_v, silent=silent)
        self.addtional_win.append(check_update_window)
        # check_update_window.show()

    def show_refer_notes(self):
        setting_ = Setting()
        if setting_.is_firstly_open():
            refer_notes = ReferenceNotes()
            # refer_notes.setWindowModality(Qt.ApplicationModal)
            self.addtional_win.append(refer_notes)

    def inspect_children(self):
        children_ = self.tab_widget.findChildren(QObject)
        for i, w_ in enumerate(children_):
            print(f"{i} - c: {w_} | oName: {w_.objectName()} | size: {sys.getsizeof(w_)}")
        print(f"Total {len(children_)} children")

    def save_to_file(self):
        self.tab_widget.currentWidget().findChild(SerialEdit).save() if isinstance(self.tab_widget.currentWidget(), SerialFrame) else self.tab_widget.currentWidget().findChild(ReaderEdit).save()

    def save_as_file(self):
        self.tab_widget.currentWidget().findChild(SerialEdit).save_as() if isinstance(self.tab_widget.currentWidget(), SerialFrame) else self.tab_widget.currentWidget().findChild(ReaderEdit).save_as()

    def open_serial(self):
        self.tab_widget.open_serial_signal.emit()

    def open_file(self):
        if self.tab_widget.count() > 0:
            file_path, _ = QFileDialog.getOpenFileName(self, 'Open File',
                                                       directory=os.path.expanduser('~/Desktop/'),
                                                       filter='Any(*);;')
            if not file_path:
                return
            # ------ 如果当前是Serial界面，则新开Reader界面，并打开文件
            if isinstance(self.tab_widget.currentWidget(), SerialFrame):
                logger.info(f"Current widget {self.tab_widget.currentWidget().objectName()}，will new a reader widget.")
                self.tab_widget.add_tab()
            self.tab_widget.currentWidget().findChild(ReaderEdit).open_pySignal.emit(file_path)

    def new_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, 'Open File',
                                                   directory=os.path.expanduser('~/Desktop/'),
                                                   filter='Any(*);;')
        if not file_path:
            return
        self.tab_widget.add_tab()
        self.tab_widget.currentWidget().findChild(ReaderEdit).open_pySignal.emit(file_path)
